/**
 * 
 */
package org.perfect.batch.configuration;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author billmse
 *
 */
@Configuration
public class QuotationJobConfiguration {

	@Autowired
	private JobBuilderFactory jobBuilderFactory;

	@Autowired
	private StepBuilderFactory stepBuilderFactory;

	public static final String JOB_NAME = "QuotationJob";
	public static final String STEP_NAME = "QuotationStep";
	public static final String STEP_READER_NAME = "QuotationStepReader";
	public static final String STEP_WRITER_NAME = "QuotationStepWriter";

	private static final int CHUNK_SIZE = 1;

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Bean(JOB_NAME)
	public Job quotationJob() throws Exception {
		return jobBuilderFactory.get(JOB_NAME).start(quotationStep()).build();
	}

	@Bean(STEP_NAME)
	public Step quotationStep() throws Exception {
		return stepBuilderFactory.get(STEP_NAME).<Quotation, Quotation>chunk(CHUNK_SIZE).reader(quotationStepReader())
				.writer(quotationStepWriter()).build();
	}

	@StepScope
	@Bean(STEP_READER_NAME)
	public ItemReader<Quotation> quotationStepReader() throws Exception {
		return new ItemReader<Quotation>() {

			private QuotationClient client = new QuotationClient("http://hq.sinajs.cn");

			@Override
			public Quotation read()
					throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
				return client.get("/list=sz162605").get(0);
			}

		};
	}

	@StepScope
	@Bean(STEP_WRITER_NAME)
	public ItemWriter<Quotation> quotationStepWriter() {
		return new ItemWriter<Quotation>() {

			@Override
			public void write(List<? extends Quotation> items) throws Exception {
				for (Quotation quotation : items) {
					logger.info("{}", quotation.getLastPrice());	
				}
			}

		};
	}

	class QuotationClient {

		private String baseUrl;
		private final static int TIMEOUT = 10000;

		public QuotationClient(String baseUrl) {
			this.baseUrl = baseUrl;
		}

		public ArrayList<Quotation> get(String path) throws Exception {
			ArrayList<Quotation> quotations = new ArrayList<Quotation>();
			HttpURLConnection connection = (HttpURLConnection) new URL(baseUrl + path).openConnection();
			connection.setConnectTimeout(TIMEOUT);
			connection.connect();
			if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
				BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GBK"));
				String line = null;
				while ((line = reader.readLine()) != null) {
					String[] data = line.substring(line.indexOf("=") + 2, line.length() - 2).split(",");
					if (data.length > 1) {
						Quotation quotation = new Quotation();
						quotation.setOpeningPrice(Float.valueOf(data[1]));
						quotation.setClosingPrice(Float.valueOf(data[2]));
						quotation.setLastPrice(Float.valueOf(data[3]));
						quotation.setHighPrice(Float.valueOf(data[4]));
						quotation.setLowPrice(Float.valueOf(data[5]));
						quotation.setVolume(Double.valueOf(data[8]));
						quotation.setTurnover(Double.valueOf(data[9]));
						quotation.setBuyingQuantityOne(Double.valueOf(data[10]));
						quotation.setBuyingPriceOne(Float.valueOf(data[11]));
						quotation.setBuyingQuantityTwo(Double.valueOf(data[12]));
						quotation.setBuyingPriceTwo(Float.valueOf(data[13]));
						quotation.setBuyingQuantityThree(Double.valueOf(data[14]));
						quotation.setBuyingPriceThree(Float.valueOf(data[15]));
						quotation.setBuyingQuantityFour(Double.valueOf(data[16]));
						quotation.setBuyingPriceFour(Float.valueOf(data[17]));
						quotation.setBuyingQuantityFive(Double.valueOf(data[18]));
						quotation.setBuyingPriceFive(Float.valueOf(data[19]));
						quotation.setSellingQuantityOne(Double.valueOf(data[20]));
						quotation.setSellingPriceOne(Float.valueOf(data[21]));
						quotation.setSellingQuantityTwo(Double.valueOf(data[22]));
						quotation.setSellingPriceTwo(Float.valueOf(data[23]));
						quotation.setSellingQuantityThree(Double.valueOf(data[24]));
						quotation.setSellingPriceThree(Float.valueOf(data[25]));
						quotation.setSellingQuantityFour(Double.valueOf(data[26]));
						quotation.setSellingPriceFour(Float.valueOf(data[27]));
						quotation.setSellingQuantityFive(Double.valueOf(data[28]));
						quotation.setSellingPriceFive(Float.valueOf(data[29]));
						quotation.setDate(FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss")
								.parse(data[data.length - 3] + " " + data[data.length - 2]));
						quotations.add(quotation);
					}
				}
				reader.close();
			}
			connection.disconnect();
			return quotations;
		}

	}

	class Quotation {

		private String id;

		private Float lastPrice;

		private Float highPrice;

		private Float lowPrice;

		private Float openingPrice;

		private Float closingPrice;

		private Float buyingPriceOne;

		private Float buyingPriceTwo;

		private Float buyingPriceThree;

		private Float buyingPriceFour;

		private Float buyingPriceFive;

		private Float sellingPriceOne;

		private Float sellingPriceTwo;

		private Float sellingPriceThree;

		private Float sellingPriceFour;

		private Float sellingPriceFive;

		private Double buyingQuantityOne;

		private Double buyingQuantityTwo;

		private Double buyingQuantityThree;

		private Double buyingQuantityFour;

		private Double buyingQuantityFive;

		private Double sellingQuantityOne;

		private Double sellingQuantityTwo;

		private Double sellingQuantityThree;

		private Double sellingQuantityFour;

		private Double sellingQuantityFive;

		private Double turnover;

		private Double volume;

		private Date date = new Date(System.currentTimeMillis());

		public Quotation() {
		}

		public String getId() {
			return id;
		}

		public void setId(String id) {
			this.id = id;
		}

		public Float getLastPrice() {
			return lastPrice;
		}

		public void setLastPrice(Float lastPrice) {
			this.lastPrice = lastPrice;
		}

		public Float getHighPrice() {
			return highPrice;
		}

		public void setHighPrice(Float highPrice) {
			this.highPrice = highPrice;
		}

		public Float getLowPrice() {
			return lowPrice;
		}

		public void setLowPrice(Float lowPrice) {
			this.lowPrice = lowPrice;
		}

		public Float getOpeningPrice() {
			return openingPrice;
		}

		public void setOpeningPrice(Float openingPrice) {
			this.openingPrice = openingPrice;
		}

		public Float getClosingPrice() {
			return closingPrice;
		}

		public void setClosingPrice(Float closingPrice) {
			this.closingPrice = closingPrice;
		}

		public Float getBuyingPriceOne() {
			return buyingPriceOne;
		}

		public void setBuyingPriceOne(Float buyingPriceOne) {
			this.buyingPriceOne = buyingPriceOne;
		}

		public Float getBuyingPriceTwo() {
			return buyingPriceTwo;
		}

		public void setBuyingPriceTwo(Float buyingPriceTwo) {
			this.buyingPriceTwo = buyingPriceTwo;
		}

		public Float getBuyingPriceThree() {
			return buyingPriceThree;
		}

		public void setBuyingPriceThree(Float buyingPriceThree) {
			this.buyingPriceThree = buyingPriceThree;
		}

		public Float getBuyingPriceFour() {
			return buyingPriceFour;
		}

		public void setBuyingPriceFour(Float buyingPriceFour) {
			this.buyingPriceFour = buyingPriceFour;
		}

		public Float getBuyingPriceFive() {
			return buyingPriceFive;
		}

		public void setBuyingPriceFive(Float buyingPriceFive) {
			this.buyingPriceFive = buyingPriceFive;
		}

		public Float getSellingPriceOne() {
			return sellingPriceOne;
		}

		public void setSellingPriceOne(Float sellingPriceOne) {
			this.sellingPriceOne = sellingPriceOne;
		}

		public Float getSellingPriceTwo() {
			return sellingPriceTwo;
		}

		public void setSellingPriceTwo(Float sellingPriceTwo) {
			this.sellingPriceTwo = sellingPriceTwo;
		}

		public Float getSellingPriceThree() {
			return sellingPriceThree;
		}

		public void setSellingPriceThree(Float sellingPriceThree) {
			this.sellingPriceThree = sellingPriceThree;
		}

		public Float getSellingPriceFour() {
			return sellingPriceFour;
		}

		public void setSellingPriceFour(Float sellingPriceFour) {
			this.sellingPriceFour = sellingPriceFour;
		}

		public Float getSellingPriceFive() {
			return sellingPriceFive;
		}

		public void setSellingPriceFive(Float sellingPriceFive) {
			this.sellingPriceFive = sellingPriceFive;
		}

		public Double getBuyingQuantityOne() {
			return buyingQuantityOne;
		}

		public void setBuyingQuantityOne(Double buyingQuantityOne) {
			this.buyingQuantityOne = buyingQuantityOne / 100;
		}

		public Double getBuyingQuantityTwo() {
			return buyingQuantityTwo;
		}

		public void setBuyingQuantityTwo(Double buyingQuantityTwo) {
			this.buyingQuantityTwo = buyingQuantityTwo / 100;
		}

		public Double getBuyingQuantityThree() {
			return buyingQuantityThree;
		}

		public void setBuyingQuantityThree(Double buyingQuantityThree) {
			this.buyingQuantityThree = buyingQuantityThree / 100;
		}

		public Double getBuyingQuantityFour() {
			return buyingQuantityFour;
		}

		public void setBuyingQuantityFour(Double buyingQuantityFour) {
			this.buyingQuantityFour = buyingQuantityFour / 100;
		}

		public Double getBuyingQuantityFive() {
			return buyingQuantityFive;
		}

		public void setBuyingQuantityFive(Double buyingQuantityFive) {
			this.buyingQuantityFive = buyingQuantityFive / 100;
		}

		public Double getSellingQuantityOne() {
			return sellingQuantityOne;
		}

		public void setSellingQuantityOne(Double sellingQuantityOne) {
			this.sellingQuantityOne = sellingQuantityOne / 100;
		}

		public Double getSellingQuantityTwo() {
			return sellingQuantityTwo;
		}

		public void setSellingQuantityTwo(Double sellingQuantityTwo) {
			this.sellingQuantityTwo = sellingQuantityTwo / 100;
		}

		public Double getSellingQuantityThree() {
			return sellingQuantityThree;
		}

		public void setSellingQuantityThree(Double sellingQuantityThree) {
			this.sellingQuantityThree = sellingQuantityThree / 100;
		}

		public Double getSellingQuantityFour() {
			return sellingQuantityFour;
		}

		public void setSellingQuantityFour(Double sellingQuantityFour) {
			this.sellingQuantityFour = sellingQuantityFour / 100;
		}

		public Double getSellingQuantityFive() {
			return sellingQuantityFive;
		}

		public void setSellingQuantityFive(Double sellingQuantityFive) {
			this.sellingQuantityFive = sellingQuantityFive / 100;
		}

		public Double getTurnover() {
			return turnover;
		}

		public void setTurnover(Double turnover) {
			this.turnover = turnover;
		}

		public Double getVolume() {
			return volume;
		}

		public void setVolume(Double volume) {
			this.volume = volume / 100;
		}

		public Date getDate() {
			return date;
		}

		public void setDate(Date date) {
			this.date = date;
		}

	}

}
